package org.web.base.domain.helper;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
import org.web.base.domain.exception.ResultMessageEnum;
import org.web.base.domain.exception.ServiceException;

//import javax.validation.ConstraintViolation;
//import javax.validation.Validation;
//import javax.validation.Validator;
//import javax.validation.ValidatorFactory;
//import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class ValidationHelper {

    private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private static final Validator validator = factory.getValidator();

    /**
     * 验证对象是否合法
     *
     * @param clazz  验证的类
     * @param object 待验证的对象
     * @param groups 验证组
     * @param <T>    泛型类型
     * @return 包含验证错误信息的列表，如果没有错误则为空列表
     */
    public static <T> List<String> validate(Class<T> clazz, T object, Class<?>... groups) {
        List<String> errorList = new ArrayList<>();
        Set<ConstraintViolation<T>> violations;

        if (object == null) {
            errorList.add("待验证对象为空。");
        } else {
            if (groups == null) {
                violations = validator.validate(object);
            } else {
                violations = validator.validate(object, groups);
            }

            for (ConstraintViolation<T> violation : violations) {
                String stringBuilder = violation.getPropertyPath() + "参数不合法，不合法信息是：" +
                        violation.getInvalidValue() + "。" +
                        violation.getMessage();
                errorList.add(stringBuilder);
            }
        }
        return errorList;
    }

    public static <T> String validateResturnString(Class<T> clazz, T object, Class<?>... groups) {
        return validate(clazz, object, groups).stream().collect(Collectors.joining("\n"));
    }

    /**
     * 验证对象是否合法
     *
     * @param clazz  验证的类
     * @param object 待验证的对象
     * @param groups 验证组
     * @param <T>    泛型类型
     * @return 没有问题，返回false, 校验有问题，返回true.
     */
    public static <T> boolean validate(@NotNull List<String> errorList, Class<T> clazz, T object, Class<?>... groups) {
        String errorInfo = validateResturnString(clazz, object, groups);
        if (StringUtils.isNoneBlank(errorInfo)) {
            errorList.add(errorInfo);
            return true;
        }
        return false;
    }

    /**
     * 验证对象是否合法
     * @param count 指定第几条记录
     * @param errorList 错误数组
     * @param clazz  验证的类
     * @param object 待验证的对象
     * @param groups 验证组
     * @param <T>    泛型类型
     * @return 没有问题，返回false, 校验有问题，返回true.
     */
    public static <T> boolean validate(Integer count, @NotNull List<String> errorList, Class<T> clazz, T object, Class<?>... groups) {
        String errorInfo = validateResturnString(clazz, object, groups);
        if (StringUtils.isNoneBlank(errorInfo)) {
            if (count == null) {
                errorList.add(errorInfo);
            } else {
                errorList.add("第"+count+"条数据信息不合法。 "+errorInfo);
            }
            return true;
        }
        return false;
    }

    /**
     * 验证对象是否合法，如果不合法则抛出 ServiceException 异常
     *
     * @param clazz  验证的类
     * @param object 待验证的对象
     * @param groups 验证组
     * @param <T>    泛型类型
     * @throws ServiceException 如果对象验证不通过，将抛出 ServiceException 异常
     */
    public static <T> void validateWithThrow(Class<T> clazz, T object, Class<?>... groups) {
        List<String> errorList = validate(clazz, object, groups);
        if (!errorList.isEmpty()) {
            String errorInfo = StringUtils.join(errorList, "\n");
            ServiceException serviceException = ServiceExceptionHelper.buildServiceException(ResultMessageEnum.PARAM_INVALID,errorInfo);
            serviceException.setErrorList(errorList);
            throw serviceException;
        }
    }

    public static String validateList(Collection<String> list, Collection<String> allowedValues, boolean ignoreCase) {
        List<String> invalidElements;

        if (ignoreCase) {
            invalidElements = list.stream()
                    .filter(element -> allowedValues.stream()
                            .noneMatch(allowedValue -> allowedValue.equalsIgnoreCase(element)))
                    .collect(Collectors.toList());
        } else {
            invalidElements = list.stream()
                    .filter(element -> !allowedValues.contains(element))
                    .collect(Collectors.toList());
        }

        return String.join(", ", invalidElements);
    }

    public static String validateList(Collection<String> list, Collection<String> allowedValues) {
        return validateList(list, allowedValues, true);
    }
}